﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace Microsoft.Office.PowerPoint.STAMP.Controls
{
    /// <summary>
    /// Form to allow you to select a color.
    /// </summary>
    public class ColorButtonSelectionPanel : Form
    {
        private int _colorIndex = -1;
        // ADDED: Ignazio Di Napoli - neclepsio@hotmail.com
        private int _keyboardIndex = -50;
        // END ADDED

        private readonly Color[] _colorList = new[]
                                                  {
                                                      Color.FromArgb( 0x00, 0x00, 0x00 ), Color.FromArgb( 0x99, 0x33, 0x00 ),
                                                      Color.FromArgb( 0x33, 0x33, 0x00 ), Color.FromArgb( 0x00, 0x33, 0x00 ),
                                                      Color.FromArgb( 0x00, 0x33, 0x66 ), Color.FromArgb( 0x00, 0x00, 0x80 ),
                                                      Color.FromArgb( 0x33, 0x33, 0x99 ), Color.FromArgb( 0x33, 0x33, 0x33 ),

                                                      Color.FromArgb( 0x80, 0x00, 0x00 ), Color.FromArgb( 0xFF, 0x66, 0x00 ),
                                                      Color.FromArgb( 0x80, 0x80, 0x00 ), Color.FromArgb( 0x00, 0x80, 0x00 ),
                                                      Color.FromArgb( 0x00, 0x80, 0x80 ), Color.FromArgb( 0x00, 0x00, 0xFF ),
                                                      Color.FromArgb( 0x66, 0x66, 0x99 ), Color.FromArgb( 0x80, 0x80, 0x80 ),

                                                      Color.FromArgb( 0xFF, 0x00, 0x00 ), Color.FromArgb( 0xFF, 0x99, 0x00 ),
                                                      Color.FromArgb( 0x99, 0xCC, 0x00 ), Color.FromArgb( 0x33, 0x99, 0x66 ),
                                                      Color.FromArgb( 0x33, 0xCC, 0xCC ), Color.FromArgb( 0x33, 0x66, 0xFF ),
                                                      Color.FromArgb( 0x80, 0x00, 0x80 ), Color.FromArgb( 0x99, 0x99, 0x99 ),

                                                      Color.FromArgb( 0xFF, 0x00, 0xFF ), Color.FromArgb( 0xFF, 0xCC, 0x00 ),
                                                      Color.FromArgb( 0xFF, 0xFF, 0x00 ), Color.FromArgb( 0x00, 0xFF, 0x00 ),
                                                      Color.FromArgb( 0x00, 0xFF, 0xFF ), Color.FromArgb( 0x00, 0xCC, 0xFF ),
                                                      Color.FromArgb( 0x99, 0x33, 0x66 ), Color.FromArgb( 0xC0, 0xC0, 0xC0 ),

                                                      Color.FromArgb( 0xFF, 0x99, 0xCC ), Color.FromArgb( 0xFF, 0xCC, 0x99 ),
                                                      Color.FromArgb( 0xFF, 0xFF, 0x99 ), Color.FromArgb( 0xCC, 0xFF, 0xCC ),
                                                      Color.FromArgb( 0xCC, 0xFF, 0xFF ), Color.FromArgb( 0x99, 0xCC, 0xFF ),
                                                      Color.FromArgb( 0xCC, 0x99, 0xFF ), Color.FromArgb( 0xFF, 0xFF, 0xFF )
                                                  };

        private readonly string _moreColorsButtonText;
        private readonly string _automaticButtonText;
        private readonly Font _currentFont;
        private Color _automaticColor;

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorButtonSelectionPanel"/> class.
        /// </summary>
        public ColorButtonSelectionPanel(Point pt, string moreColorsButtonText, string automaticButtonText, Color currentColor, Font currentFont, Color automaticColor)
        {
            _automaticButtonText = automaticButtonText;
            _automaticColor = automaticColor;
            _currentFont = currentFont;
            _moreColorsButtonText = moreColorsButtonText;
            CurrentColor = currentColor;

            FormBorderStyle = FormBorderStyle.FixedDialog;
            MinimizeBox = false;
            MaximizeBox = false;
            ControlBox = false;
            ShowInTaskbar = false;
            TopMost = true;

            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            Width = 156;
            Height = 100;

            if (FontColorButtonHasAutomatic)
                Height += 23;
            if (FontColorButtonHasMoreColors)
                Height += 23;

            CenterToScreen();
            Location = pt;

            Capture = true;
        }

        /// <summary>
        /// Gets or sets the currently selected color.
        /// </summary>
        public Color CurrentColor { get; set; }

        private bool FontColorButtonHasMoreColors
        {
            get { return _moreColorsButtonText != string.Empty; }
        }

        private bool FontColorButtonHasAutomatic
        {
            get { return _automaticButtonText != string.Empty; }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Pen darkPen = new Pen(SystemColors.ControlDark);
            Pen lightPen = new Pen(SystemColors.ControlLightLight);
            SolidBrush lightBrush = new SolidBrush(SystemColors.ControlLightLight);
            bool selected = false;
            int x = 6, y = 5;

            if (FontColorButtonHasAutomatic)
            {
                selected = CurrentColor == Color.Transparent;
                DrawButton(e, x, y, _automaticButtonText, 100, selected);
                y += 23;
            }

            for (int i = 0; i < 40; i++)
            {
                if (CurrentColor.ToArgb() == _colorList[i].ToArgb())
                    selected = true;

                if (_colorIndex == i)
                {
                    e.Graphics.DrawRectangle(lightPen, x - 3, y - 3, 17, 17);
                    e.Graphics.DrawLine(darkPen, x - 2, y + 14, x + 14, y + 14);
                    e.Graphics.DrawLine(darkPen, x + 14, y - 2, x + 14, y + 14);
                }
                else if (CurrentColor.ToArgb() == _colorList[i].ToArgb())
                {
                    // ADDED: Ignazio Di Napoli - neclepsio@hotmail.com
                    if (_keyboardIndex == -50)
                        _keyboardIndex = i;
                    // END ADDED

                    e.Graphics.FillRectangle(lightBrush, x - 3, y - 3, 18, 18);
                    e.Graphics.DrawLine(darkPen, x - 3, y - 3, x + 13, y - 3);
                    e.Graphics.DrawLine(darkPen, x - 3, y - 3, x - 3, y + 13);
                }

                e.Graphics.FillRectangle(new SolidBrush(_colorList[i]), x, y, 11, 11);
                e.Graphics.DrawRectangle(darkPen, x, y, 11, 11);

                if ((i + 1) % 8 == 0)
                {
                    x = 6;
                    y += 18;
                }
                else
                    x += 18;
            }

            if (FontColorButtonHasMoreColors)
                DrawButton(e, x, y, _moreColorsButtonText, 101, !selected);
        }

        // ADDED: Ignazio Di Napoli - neclepsio@hotmail.com
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
                Close();
            else if (e.KeyCode == Keys.Left)
                MoveIndex(-1);
            else if (e.KeyCode == Keys.Up)
                MoveIndex(-8);
            else if (e.KeyCode == Keys.Down)
                MoveIndex(+8);
            else if (e.KeyCode == Keys.Right)
                MoveIndex(+1);
            else if (e.KeyCode == Keys.Enter ||
                     e.KeyCode == Keys.Space)
                OnClick(EventArgs.Empty);
            else
                base.OnKeyDown(e);
        }

        private void MoveIndex(int delta)
        {
            int lbound = (FontColorButtonHasAutomatic ? -8 : 0);
            int ubound = 39 + (FontColorButtonHasMoreColors ? 8 : 0);
            int d = ubound - lbound + 1;

            if (delta == -1 && _keyboardIndex < 0)
                _keyboardIndex = ubound;
            else if (delta == 1 && _keyboardIndex > 39)
                _keyboardIndex = lbound;
            else if (delta == 1 && _keyboardIndex < 0)
                _keyboardIndex = 0;
            else if (delta == -1 && _keyboardIndex > 39)
                _keyboardIndex = 39;
            else
                _keyboardIndex += delta;

            if (_keyboardIndex < lbound)
                _keyboardIndex += d;
            if (_keyboardIndex > ubound)
                _keyboardIndex -= d;

            if (_keyboardIndex < 0)
                _colorIndex = 100;
            else if (_keyboardIndex > 39)
                _colorIndex = 101;
            else
                _colorIndex = _keyboardIndex;

            Refresh();
        }
        // END ADDED

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (RectangleToScreen(ClientRectangle).Contains(Cursor.Position))
                base.OnMouseDown(e);
            else
                Close();
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (RectangleToScreen(ClientRectangle).Contains(Cursor.Position))
            {
                Point pt = PointToClient(Cursor.Position);
                int x = 6, y = 5;

                if (FontColorButtonHasAutomatic)
                {
                    if (SetColorIndex(new Rectangle(x - 3, y - 3, 143, 22), pt, 100))
                        return;

                    y += 23;
                }

                for (int i = 0; i < 40; i++)
                {
                    if (SetColorIndex(new Rectangle(x - 3, y - 3, 17, 17), pt, i))
                        return;

                    if ((i + 1) % 8 == 0)
                    {
                        x = 6;
                        y += 18;
                    }
                    else
                        x += 18;
                }

                if (FontColorButtonHasMoreColors)
                {
                    if (SetColorIndex(new Rectangle(x - 3, y - 3, 143, 22), pt, 101))
                        return;
                }
            }

            if (_colorIndex != -1)
            {
                _colorIndex = -1;
                Invalidate();
            }
        }

        protected override void OnClick(EventArgs e)
        {
            if (_colorIndex < 0)
                return;

            if (_colorIndex < 40)
                CurrentColor = _colorList[_colorIndex];
            else if (_colorIndex == 100)
                CurrentColor = _automaticColor;
            else
            {
                ColorDialog dlg = new ColorDialog
                                      {
                                          Color = CurrentColor, 
                                          FullOpen = true
                                      };

                if (dlg.ShowDialog(this) != DialogResult.OK)
                {
                    Close();
                    return;
                }

                CurrentColor = dlg.Color;
            }

            Close();
        }

        private void DrawButton(PaintEventArgs e, int x, int y, string text,
                                  int index, bool selected)
        {
            Pen darkPen = new Pen(SystemColors.ControlDark);
            Pen lightPen = new Pen(SystemColors.ControlLightLight);
            SolidBrush lightBrush = new SolidBrush(SystemColors.ControlLightLight);

            if (_colorIndex == index)
            {
                e.Graphics.DrawRectangle(lightPen, x - 3, y - 3, 143, 22);
                e.Graphics.DrawLine(darkPen, x - 2, y + 19, x + 140, y + 19);
                e.Graphics.DrawLine(darkPen, x + 140, y - 2, x + 140, y + 19);
            }
            else if (selected)
            {
                e.Graphics.FillRectangle(lightBrush, x - 3, y - 3, 144, 23);
                e.Graphics.DrawLine(darkPen, x - 3, y - 3, x + 139, y - 3);
                e.Graphics.DrawLine(darkPen, x - 3, y - 3, x - 3, y + 18);
            }

            Rectangle rc = new Rectangle(x, y, 137, 16);
            SolidBrush textBrush = new SolidBrush(SystemColors.ControlText);

            StringFormat textFormat = new StringFormat
                                          {
                                              Alignment = StringAlignment.Center,
                                              LineAlignment = StringAlignment.Center
                                          };

            e.Graphics.DrawRectangle(darkPen, rc);
            e.Graphics.DrawString(text, _currentFont, textBrush, rc, textFormat);
        }

        private bool SetColorIndex(Rectangle rc, Point pt, int index)
        {
            if (rc.Contains(pt))
            {
                if (_colorIndex != index)
                {
                    _colorIndex = index;
                    Invalidate();
                }

                return true;
            }

            return false;
        }

        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ColorButtonSelectionPanel));
            this.SuspendLayout();
            // 
            // ColorButtonSelectionPanel
            // 
            resources.ApplyResources(this, "$this");
            this.Name = "ColorButtonSelectionPanel";
            this.ResumeLayout(false);

        }
    }
}